Jupyter ImageMapping Calculation
Requirements Documents:
Specification:
Implementation:
Repository: GIT ImageMapping Calculation
1.0.3 06.06.2018 ZAS1.0.2 21.02.2018 ZAS1.0.1 09.02.2018 ZAS1.0.0 05.02.2018 ZASv1.0.0Calculation of FPGA image mapping .map file for nozzle correction for conical shapes $$Resolution{2} = Resolution{1} \frac{Diameter{1}}{Diameter{2}} = [dpi]$$ $$Position{corrected}(heigth) = Position{theoretical}*\frac{Resolution{native}}{Resolution{height}} = [px]$$ $$Correction = Position{theoretical} - Position{corrected} = [px]$$
Script output can be found \p46\WpWiki-Media\internal\ipynb\VHDL\ImageMapping_Correction\
In [1]:
import os
import csv
import struct
import math
def geometricalCorrection(filename, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive=False, starting_row_offset=0):
debug = False
inch2mm = 25.4 # mm/inch
resolution_x2y = resolutions[0]/resolutions[1]
pixel_pitch_x_top = (inch2mm/float(resolutions[0]))
pixel_pitch_y = (inch2mm/float(resolutions[1]))
fileloc = "ImageMapping_Correction\\{0}\\".format(filename)
if not os.path.exists(fileloc):
os.mkdir(fileloc)
filename = fileloc + filename
################################################################################################
# Pixel Calculation
#
resolution_x_bot = resolutions[0]*(d_top/d_bot)
pixel_pitch_x_bot = (inch2mm/float(resolution_x_bot))
circumference_top = d_top*math.pi
circumference_bot = d_bot*math.pi
# size_px = [px_x_top, px_x_bot, px_y]
size_px = [int(circumference_top/pixel_pitch_x_top), int(circumference_bot/pixel_pitch_x_bot), int(height/pixel_pitch_y)] # x_top, x_bot, y
# printhead_rows middle adjusted
printhead_row_adj = []
for row in printhead_rows:
# Symetrical Resolutions
#printhead_row_adj.append( row - (printhead_rows[-1] - printhead_rows[0])/2 )
# Asymmetrical Resolutions
printhead_row_adj.append( (row - (printhead_rows[-1] - printhead_rows[0])/2) * resolution_x2y )
################################################################################################
# Printheads positions
#
height_temp = 0
# printheads = [px_y_start, px_y_stop]
printheads = []
while height_temp < size_px[2]:
if (size_px[2] - height_temp) > printhead_pixel:
printheads.append([height_temp, height_temp+printhead_pixel-1])
height_temp = height_temp+printhead_pixel-printhead_overlap
else:
printheads.append([height_temp, height_temp+(size_px[2] - height_temp)-1])
height_temp = height_temp+(size_px[2] - height_temp)
################################################################################################
# Calculation Geometry
#
# corrections = [y_px, ph_row_nbr, correction_x]
corrections = []
# Calculation Missing Pixels
if len(printheads) > 1:
printhead_stitching = (len(printheads)-1) * printhead_overlap
else:
printhead_stitching = 0
printhead_height = len(printheads)*printhead_pixel - printhead_stitching
missing_px = printhead_height - size_px[2]
# Add missing pixel to last printhead
printheads[-1][-1] += missing_px
## Works for 22oz but only 2 px missing =================================================
## Add missing Pixels with 0 correction
#for i in range(missing_px):
# row_nbr = len(printhead_rows)-1 - (i%4)
# corrections.append([size_px[2]+(missing_px-i),row_nbr,0])
# Calculation diameter
delta_d = (d_top - d_bot)/2
tan_alpha = float(delta_d)/height
y = 0
while (y < int(size_px[2])):
y_mm = y * pixel_pitch_y
# Calculating row and perform shift 0 - 1 - 2 - 3 => 1 - 2 - 3 - 0
row_nbr = ((y+2+starting_row_offset)%4) # works with 16oz and 22oz? =================================================
#row_nbr = ((y+missing_px+3)%4) # works with 16oz =================================================
#row_nbr = ((y+missing_px+2)%4) # work with 22oz =================================================
# and inverting 0 - 1 - 2 - 3 => 3 - 2 - 1 - 0
# row_nbr = len(printhead_rows)-1 - ((y+missing_px+0)%4)
# For asymetric row's 0 - 1 - 2 - 3 => 0 - 2 - 1 - 3
if row_nbr == 0:
row_nbr = 0
elif row_nbr == 1:
row_nbr = 2
elif row_nbr == 2:
row_nbr = 1
elif row_nbr == 3:
row_nbr = 3
#####################################################
# Calculation diameter
d_y = d_bot + 2*(tan_alpha*(height-y_mm))
d_y_px = d_y/pixel_pitch_y
resolution_y = resolutions[0]*(d_top/d_y)
if debug:
print("y = {:>1.5}mm row_nbr = {} d_y = {:.5}mm = {}px, res_y = {}dpi".format(height-y_mm, row_nbr, d_y, d_y_px, resolution_y))
corrections.append([int(size_px[2])-y, row_nbr, int(round(printhead_row_adj[row_nbr]-(printhead_row_adj[row_nbr] * resolution_y/resolutions[0]))), int(math.ceil(printhead_row_adj[row_nbr]-(printhead_row_adj[row_nbr] * resolution_y/resolutions[0]))), int(math.floor(printhead_row_adj[row_nbr]-(printhead_row_adj[row_nbr] * resolution_y/resolutions[0]))), printhead_row_adj[row_nbr]-(printhead_row_adj[row_nbr] * resolution_y/resolutions[0]) ])
# increment y
y = y + 1
# Add missing Pixels with 0 correction work with 16oz and 22oz? =============================================
for i in range(missing_px):
row_nbr = len(printhead_rows)-1 - (i%4)
corrections.append([(missing_px-i),row_nbr,0, 0, 0, 0])
print("")
# Eliminate negative values
if only_positive:
correction = list(zip(*corrections))[2]
min_value = min(correction)
#print("min: {} px max: {} px".format(min_value, max(correction)))
if min_value < 0:
for y in range(len(corrections)):
corrections[y][2] = corrections[y][2] + abs(min_value)
################################################################################################
# Print Substrate Data
#
print("-- Resolutions -------------------------------")
print(" X-Top = {} dpi".format(resolutions[0]))
print(" X-Bottom = {} dpi".format(resolution_x_bot))
print(" Y = {} dpi".format(resolutions[1]))
print("")
print("-- Size --------------------------------------")
print(" X-Top = {:.05} mm @ {:} dpi = {} px".format(circumference_top, resolutions[0], size_px[0], int(size_px[0])))
print(" X-Bottom = {:.05} mm @ {:.5} dpi = {} px".format(circumference_bot, resolution_x_bot, size_px[1], int(size_px[1])))
print(" Y = {:.05} mm @ {:} dpi = {} px".format(height, resolutions[1], size_px[2], int(size_px[2])))
print("")
################################################################################################
# Print Printhead Data
#
print("-- Printheads --------------------------------")
print(" Number of PH = {} Pcs".format(len(printheads)))
print(" PH Overlap = {} px".format(printhead_overlap))
for i in range(len(printheads)):
print(" PH{}: Y-Position = {: 5} px --> {: 5} px".format(i, printheads[i][0], printheads[i][1]))
print(" Printhead Rows = {:3}px {:3}px {:3}px {:3}px @ {}dpi".format(printhead_rows[0], printhead_rows[1], printhead_rows[2], printhead_rows[3], resolutions[1]))
print(" Printhead Rows Adjusted = {:3}px {:3}px {:3}px {:3}px @ {}dpi".format(printhead_row_adj[0], printhead_row_adj[1], printhead_row_adj[2], printhead_row_adj[3], resolutions[0]))
print(" Image Height = {} px / Printhead Height = {} px => Missing {} px".format(size_px[2], printhead_height, missing_px))
print("")
################################################################################################
# Print Correction
#
print("-- Nozzle Correction Map Start and End -------")
print("| Idx | Height | Row | Correction |")
print("+------+--------+-----+------------+")
for y in range(len(corrections)):
#if y < 10 or y > (size_px[2]-10):
if y < 10 or y > (printheads[-1][-1]-10):
print("| {:4} | {:4}px | {:3} | {:7} px |".format(y, corrections[y][0], corrections[y][1], corrections[y][2]))
elif y == 10:
print("| ... | ... | ... | ... |")
print("")
################################################################################################
# Write complete output files
print("-- Write Output Files ------------------------")
# Write output into text file
binary_fname = "{}_Full.map".format(filename)
print("Write Correction into {}".format(binary_fname))
with open(binary_fname, "wb") as binary_file:
for correction in corrections:
binary_file.write(struct.pack('b',correction[2]))
# Write output into csv file
csv_fname = "{}_Full.csv".format(filename)
print("Write Correction into {}".format(csv_fname))
with open(csv_fname, "w") as csv_file:
wr = csv.writer(csv_file, delimiter=';', lineterminator='\n')
wr.writerow(["Pixel", "Row", "Round Correction Value Signed", "Round Correction Value Unsigned", "Ceil Correction Value", "Floor Correction Value", "Float Correction Value" ])
for correction in corrections:
if correction[2] < 0:
wr.writerow([correction[0], correction[1], correction[2], 256+correction[2], correction[3], correction[4], correction[5]])
else:
wr.writerow([correction[0], correction[1], correction[2], correction[2], correction[3], correction[4], correction[5]])
print("")
################################################################################################
# Write Output Files per head
#
print("-- Write Output Files per Printhead ----------")
# Write output into text file
ph_idx = 0
fname = "{}_{}.map".format(filename, ph_idx)
binary_file = open(fname, "wb")
for printhead in printheads:
binary_file.close()
fname = "{}_{}.map".format(filename, ph_idx)
ph_idx = ph_idx + 1
binary_file = open(fname, "wb")
print("Write PH{} Correction into {}".format(ph_idx, fname))
for y in range(printhead[0], printhead[1]+1):
#print("start {} stop {} current {} value {}".format(printhead[0], printhead[1]+1, y,corrections[y][2]))
binary_file.write(struct.pack('b',corrections[y][2]))
binary_file.close
# Write output into csv file
ph_idx = 0
fname = "{}_{}.csv".format(filename, ph_idx)
csv_file = open(fname, "w")
for printhead in printheads:
csv_file.close()
fname = "{}_{}.csv".format(filename, ph_idx)
ph_idx = ph_idx + 1
csv_file = open(fname, "w")
wr = csv.writer(csv_file, delimiter=';')
wr.writerow(["Pixel", "Row", "Correction Value Signed", "Correction Value Unsigned"])
print("Write PH{} Correction into {}".format(ph_idx, fname))
for y in range(printhead[0], printhead[1]+1):
#print("start {} stop {} current {} value {}".format(printhead[0], printhead[1]+1, y,corrections[y][2]))
if corrections[y][2] < 0:
wr.writerow([corrections[y][0], corrections[y][1], corrections[y][2], 256+corrections[y][2]])
else:
wr.writerow([corrections[y][0], corrections[y][1], corrections[y][2], corrections[y][2]])
csv_file.close()
In [14]:
# Substrat Name
name = "NoCorrection"
# Substrate
d_top = 1.0 # [mm] Diameter Top
d_bot = 1.0 # [mm] Diameter Bottom
height = 72.248889 # [mm] Height == 1024 px
# Machine
resolutions = [360,360] # [dpi_x, dpi_y]
printhead_overlap = 0 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [2]:
# Substrate Name
name = "Cup_22Oz_360dpi_new"
# Substrate
d_top = 89.154 # [mm] Diameter Top
d_bot = 66.833 # [mm] Diameter Bottom
height = 142.12 # [mm] Height
# Machine
resolutions = [360,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [16]:
# Substrate Name
name = "Cup_22Oz_720_360dpi"
# Substrate
d_top = 89.154 # [mm] Diameter Top
d_bot = 66.833 # [mm] Diameter Bottom
height = 142.12 # [mm] Height
# Machine
resolutions = [720,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [17]:
# Substrate Name
name = "Cup_16Oz_Raijshree_720_360dpi"
# Substrate
d_top = 78.6 # [mm] Diameter Top
d_bot = 56.68 # [mm] Diameter Bottom
height = 108.45 # [mm] Height
# Machine
resolutions = [720,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [18]:
# Substrate Name
name = "Cup_250ml_Greiner_360_360dpi"
# Substrate
d_top = 70.0 # [mm] Diameter Top
d_bot = 54.3569 # [mm] Diameter Bottom
height = 100.0395 # [mm] Height
# Machine
resolutions = [360,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [11]:
# Substrate Name
name = "Cup_250ml_Greiner_720_360dpi"
# Substrate
d_top = 70.0 # [mm] Diameter Top
d_bot = 54.3569 # [mm] Diameter Bottom
height = 100.0395 # [mm] Height
# Machine
resolutions = [720,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [24]:
# Substrate Name
name = "Cup_64oz_WNA_360_360dpi"
# Substrate
d_top = 112.0 # [mm] Diameter Top
d_bot = 92.18 # [mm] Diameter Bottom
height = 212.24 #241.3-14.79-14.79 (values in design)# [mm] Height
# Machine
resolutions = [360,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [8]:
# Substrate Name
name = "Cup_64oz_WNA_720_360dpi"
# Substrate
d_top = 112.0 # [mm] Diameter Top
d_bot = 92.18 # [mm] Diameter Bottom
height = 212.24 # [mm] Height
# Machine
resolutions = [720,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)
In [61]:
# Substrate Name
name = "Cup_64oz_WNA_360_360dpi"
# Substrate
d_top = 112.0 # [mm] Diameter Top
d_bot = 92.18 # [mm] Diameter Bottom
height = 212.24 # [mm] Height
# Machine
resolutions = [360,360] # [dpi_x, dpi_y]
printhead_overlap = 32 # [px] overlap between printheads
# Printhead
printhead_rows = [0, 11.991, 27.982, 39.973] # px exact
printhead_rows = [0, 12, 28, 40] # px rounded
printhead_pixel = 1024 # [px] KM1024i
only_positive = True # allow only positive values in output file
geometricalCorrection(name, d_top, d_bot, height, resolutions, printhead_overlap, printhead_rows, printhead_pixel, only_positive)